{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 第六章：卷积神经网络\n",
    "湖北理工学院《机器学习》课程资料\n",
    "\n",
    "作者：李辉楚吴\n",
    "\n",
    "笔记内容概述: 卷积神经网络、手写字母识别"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test set size: 10000\n",
      "Training set size: 60000\n",
      "Number of training samples: 43360\n",
      "Number of cross-validation samples: 10850\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import torchvision\n",
    "import torchvision.transforms as transforms\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "label_size = 18 # Label size\n",
    "ticklabel_size = 14 # Tick label size\n",
    "    \n",
    "# Define a transform to normalize the data\n",
    "transform = transforms.Compose([\n",
    "    transforms.ToTensor()\n",
    "])\n",
    "\n",
    "# Load test data from the MNIST\n",
    "testset = torchvision.datasets.MNIST(root='./Data', train=False, download=False, transform=transform)\n",
    "print(f\"Test set size: {len(testset)}\")\n",
    "\n",
    "# Load training data from the MNIST\n",
    "trainset = torchvision.datasets.MNIST(root='./Data', train=True, download=False, transform=transform)\n",
    "print(f\"Training set size: {len(trainset)}\")\n",
    "\n",
    "# Rate of trX and cvX\n",
    "tr_cv_rate = 0.8\n",
    "\n",
    "# Create a list to store indices for each class unique()\n",
    "class_indices = [[] for _ in range(10)]  # 10 classes in MNIST\n",
    "\n",
    "# Populate class_indices\n",
    "for idx, (_, label) in enumerate(trainset):\n",
    "    class_indices[label].append(idx)\n",
    "\n",
    "# Calculate the number of samples for each class in training and validation sets\n",
    "train_size_per_class = int(tr_cv_rate * min(len(indices) for indices in class_indices))\n",
    "val_size_per_class = min(len(indices) for indices in class_indices) - train_size_per_class\n",
    "\n",
    "# Create balanced train and validation sets\n",
    "train_indices = []\n",
    "val_indices = []\n",
    "for indices in class_indices:\n",
    "    train_indices.extend(indices[:train_size_per_class])\n",
    "    val_indices.extend(indices[train_size_per_class:train_size_per_class + val_size_per_class])\n",
    "\n",
    "# Create Subset datasets\n",
    "from torch.utils.data import Subset\n",
    "trX = Subset(trainset, train_indices)\n",
    "cvX = Subset(trainset, val_indices)\n",
    "\n",
    "print(f\"Number of training samples: {len(trX)}\")\n",
    "print(f\"Number of cross-validation samples: {len(cvX)}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "构建DataLoaders，准备训练模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "image_channels is 1\n",
      "tensor([[0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],\n",
      "        [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],\n",
      "        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],\n",
      "        [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.]])\n"
     ]
    }
   ],
   "source": [
    "batch_size = 42 # Define training batch 1，\n",
    "\n",
    "def one_hot_collate(batch):\n",
    "    data = torch.stack([item[0] for item in batch])\n",
    "    labels = torch.tensor([item[1] for item in batch])\n",
    "    one_hot_labels = torch.zeros(labels.size(0), 10)  # 10 classes in MNIST 【0，1，0，0】\n",
    "    one_hot_labels.scatter_(1, labels.unsqueeze(1), 1)\n",
    "    return data, one_hot_labels\n",
    "\n",
    "trLoader = torch.utils.data.DataLoader(trX, batch_size=batch_size, shuffle=True, num_workers=0, collate_fn=one_hot_collate)\n",
    "cvLoader = torch.utils.data.DataLoader(cvX, batch_size=batch_size, shuffle=False, num_workers=0, collate_fn=one_hot_collate)\n",
    "teLoader = torch.utils.data.DataLoader(testset, batch_size=batch_size, shuffle=False, num_workers=0, collate_fn=one_hot_collate)\n",
    "\n",
    "# Get a batch of training data\n",
    "dataiter = iter(trLoader)\n",
    "data, labels = next(dataiter)\n",
    "\n",
    "image_channels = data[0].numpy().shape[0]\n",
    "print(f'image_channels is {image_channels}')\n",
    "print(labels)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 定义并训练卷积神经网络\n",
    "* 输入：2-D图片\n",
    "* 输出：手写字母类型的概率分布\n",
    "* 卷积层：2层, 卷积核大小：3x3\n",
    "* 隐藏层1：100个节点\n",
    "* 隐藏层2：50个节点"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CNN(\n",
      "  (conv1): Conv2d(1, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
      "  (pool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
      "  (conv2): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
      "  (pool2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
      "  (fc1): Linear(in_features=3136, out_features=100, bias=True)\n",
      "  (fc2): Linear(in_features=100, out_features=10, bias=True)\n",
      "  (softmax): Softmax(dim=1)\n",
      ")\n"
     ]
    }
   ],
   "source": [
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "import torch.optim as optim\n",
    "\n",
    "class CNN(nn.Module):\n",
    "    def __init__(self, image_channels, num_classes):\n",
    "        super(CNN, self).__init__()\n",
    "        \n",
    "        # First convolutional layer\n",
    "        self.conv1 = nn.Conv2d(in_channels=image_channels, out_channels=32, kernel_size=3, padding=1)\n",
    "        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)\n",
    "        \n",
    "        # Second convolutional layer\n",
    "        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)\n",
    "        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)\n",
    "        \n",
    "        # Fully connected layers\n",
    "        self.fc1 = nn.Linear(64 * 7 * 7, 100)  # After two 2x2 max pools, 28x28 -> 7x7\n",
    "        self.fc2 = nn.Linear(100, num_classes)  # 10 classes output\n",
    "\n",
    "        # Softmax\n",
    "        self.softmax = nn.Softmax(dim=1)\n",
    "        \n",
    "    def forward(self, x):\n",
    "        # Remove the reshape operation and directly use x\n",
    "        x = F.relu(self.conv1(x))\n",
    "        x = self.pool1(x)\n",
    "        \n",
    "        # Second conv layer\n",
    "        x = F.relu(self.conv2(x))\n",
    "        x = self.pool2(x)\n",
    "        \n",
    "        # Flatten the output for the fully connected layers\n",
    "        x = x.view(-1, 64 * 7 * 7)\n",
    "        \n",
    "        # Fully connected layers\n",
    "        x = F.relu(self.fc1(x))\n",
    "        x = self.fc2(x)\n",
    "        \n",
    "        # Softmax\n",
    "        x = self.softmax(x)\n",
    "        \n",
    "        return x\n",
    "\n",
    "# Initialize the model\n",
    "model = CNN(image_channels, 10)\n",
    "if torch.cuda.is_available():\n",
    "    model = model.cuda()\n",
    "\n",
    "# Display model architecture\n",
    "print(model)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用Adam作为Optimizor训练模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch [1/50], Train Loss: 1.5518, CV Loss: 1.5039\n",
      "Epoch [2/50], Train Loss: 1.4871, CV Loss: 1.4862\n",
      "Epoch [3/50], Train Loss: 1.4805, CV Loss: 1.4859\n",
      "Epoch [4/50], Train Loss: 1.4768, CV Loss: 1.4832\n",
      "Epoch [5/50], Train Loss: 1.4754, CV Loss: 1.4804\n",
      "Epoch [6/50], Train Loss: 1.4741, CV Loss: 1.4804\n",
      "Epoch [7/50], Train Loss: 1.4718, CV Loss: 1.4827\n",
      "Epoch [8/50], Train Loss: 1.4715, CV Loss: 1.4813\n",
      "Epoch [9/50], Train Loss: 1.4710, CV Loss: 1.4780\n",
      "Epoch [10/50], Train Loss: 1.4707, CV Loss: 1.4772\n",
      "Epoch [11/50], Train Loss: 1.4695, CV Loss: 1.4769\n",
      "Epoch [12/50], Train Loss: 1.4699, CV Loss: 1.4785\n",
      "Epoch [13/50], Train Loss: 1.4692, CV Loss: 1.4790\n",
      "Epoch [14/50], Train Loss: 1.4684, CV Loss: 1.4775\n",
      "Epoch [15/50], Train Loss: 1.4679, CV Loss: 1.4778\n",
      "Epoch [16/50], Train Loss: 1.4676, CV Loss: 1.4775\n",
      "Epoch [17/50], Train Loss: 1.4672, CV Loss: 1.4778\n",
      "Epoch [18/50], Train Loss: 1.4684, CV Loss: 1.4774\n",
      "Epoch [19/50], Train Loss: 1.4678, CV Loss: 1.4773\n",
      "Epoch [20/50], Train Loss: 1.4670, CV Loss: 1.4771\n",
      "Epoch [21/50], Train Loss: 1.4670, CV Loss: 1.4781\n",
      "Epoch [22/50], Train Loss: 1.4669, CV Loss: 1.4766\n",
      "Epoch [23/50], Train Loss: 1.4671, CV Loss: 1.4813\n",
      "Epoch [24/50], Train Loss: 1.4671, CV Loss: 1.4820\n",
      "Epoch [25/50], Train Loss: 1.4665, CV Loss: 1.4761\n",
      "Epoch [26/50], Train Loss: 1.4667, CV Loss: 1.4762\n",
      "Epoch [27/50], Train Loss: 1.4662, CV Loss: 1.4763\n",
      "Epoch [28/50], Train Loss: 1.4668, CV Loss: 1.4741\n",
      "Epoch [29/50], Train Loss: 1.4662, CV Loss: 1.4768\n",
      "Epoch [30/50], Train Loss: 1.4660, CV Loss: 1.4772\n",
      "Epoch [31/50], Train Loss: 1.4661, CV Loss: 1.4744\n",
      "Epoch [32/50], Train Loss: 1.4662, CV Loss: 1.4751\n",
      "Epoch [33/50], Train Loss: 1.4661, CV Loss: 1.4772\n",
      "Epoch [34/50], Train Loss: 1.4647, CV Loss: 1.4730\n",
      "Epoch [35/50], Train Loss: 1.4660, CV Loss: 1.4759\n",
      "Epoch [36/50], Train Loss: 1.4658, CV Loss: 1.4769\n",
      "Epoch [37/50], Train Loss: 1.4657, CV Loss: 1.4745\n",
      "Epoch [38/50], Train Loss: 1.4653, CV Loss: 1.4767\n",
      "Epoch [39/50], Train Loss: 1.4657, CV Loss: 1.4745\n",
      "Epoch [40/50], Train Loss: 1.4654, CV Loss: 1.4746\n",
      "Epoch [41/50], Train Loss: 1.4654, CV Loss: 1.4739\n",
      "Epoch [42/50], Train Loss: 1.4660, CV Loss: 1.4758\n",
      "Epoch [43/50], Train Loss: 1.4648, CV Loss: 1.4750\n",
      "Epoch [44/50], Train Loss: 1.4655, CV Loss: 1.4768\n",
      "Epoch [45/50], Train Loss: 1.4648, CV Loss: 1.4755\n",
      "Epoch [46/50], Train Loss: 1.4658, CV Loss: 1.4748\n",
      "Epoch [47/50], Train Loss: 1.4647, CV Loss: 1.4760\n",
      "Epoch [48/50], Train Loss: 1.4661, CV Loss: 1.4771\n",
      "Epoch [49/50], Train Loss: 1.4657, CV Loss: 1.4732\n",
      "Epoch [50/50], Train Loss: 1.4670, CV Loss: 1.4752\n"
     ]
    }
   ],
   "source": [
    "# Define loss function and optimizer\n",
    "criterion = nn.CrossEntropyLoss() # Loss\n",
    "optimizer = torch.optim.Adam(model.parameters()) # Adam\n",
    "\n",
    "# Lists to store losses\n",
    "train_losses = []\n",
    "cv_losses = []\n",
    "\n",
    "# Number of epochs\n",
    "num_epochs = 50\n",
    "\n",
    "for epoch in range(num_epochs):\n",
    "    model.train()\n",
    "    batch_losses = []\n",
    "    \n",
    "    for batch_x, batch_y in trLoader:\n",
    "        # Forward pass\n",
    "        outputs = model(batch_x)\n",
    "        loss = criterion(outputs, batch_y)\n",
    "        \n",
    "        # Backward pass and optimize\n",
    "        optimizer.zero_grad()\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "        \n",
    "        batch_losses.append(loss.item())\n",
    "    \n",
    "    # Calculate average training loss for this epoch\n",
    "    avg_train_loss = sum(batch_losses) / len(batch_losses)\n",
    "    train_losses.append(avg_train_loss)\n",
    "    \n",
    "    # Evaluate on cross-validation set\n",
    "    model.eval()\n",
    "    cv_batch_losses = []\n",
    "    with torch.no_grad():\n",
    "        for cv_x, cv_y in cvLoader:\n",
    "            cv_outputs = model(cv_x)\n",
    "            cv_loss = criterion(cv_outputs, cv_y)\n",
    "            cv_batch_losses.append(cv_loss.item())\n",
    "    \n",
    "    avg_cv_loss = sum(cv_batch_losses) / len(cv_batch_losses)\n",
    "    cv_losses.append(avg_cv_loss)\n",
    "    \n",
    "    print(f'Epoch [{epoch+1}/{num_epochs}], Train Loss: {avg_train_loss:.4f}, CV Loss: {avg_cv_loss:.4f}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "计算识别精度，展示学习曲线"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy on training set: 99.62%\n",
      "Accuracy on cross-validation set: 98.60%\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA1cAAAHUCAYAAADWedKvAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAACEJ0lEQVR4nO3dd3xTVf8H8M9N2qZ7b+hglAIFyp6yZxmyVJYCivqoOPihPoqKoKAoDtAHQUUFFQVEEAd7gwwBoYAsGYVCBy2F7jZJk/v74zRpQ1voSJuk/bxfr7yS3NzcnKS3kE/POd8jybIsg4iIiIiIiKpEYekGEBERERER1QYMV0RERERERGbAcEVERERERGQGDFdERERERERmwHBFRERERERkBgxXREREREREZsBwRUREREREZAYMV0RERERERGbAcEVERERERGQGDFdEVGdIklSuy+7du6v0OrNnz4YkSZV67u7du83SBms3efJkhIeHl2tfvV6P77//Hv369YOvry/s7e3h7++PoUOH4vfff4der6/exlbRiRMnIEkSXn311TL3uXDhAiRJwvPPP1/u45Z2nvXq1Qu9evW653OvXLkCSZKwfPnycr+ewZkzZzB79mxcuXKlxGMV+bmamyRJePbZZy3y2kREBnaWbgARUU05ePCgyf05c+Zg165d2Llzp8n25s2bV+l1Hn/8cQwaNKhSz23bti0OHjxY5TbUFvn5+RgxYgS2bt2KsWPHYsmSJQgMDERqaio2b96MBx98EKtXr8bw4cMt3dQyRUdHo127dvjuu+/wzjvvQKlUlthn2bJlAIApU6ZU6bUWL15cpeeXx5kzZ/DWW2+hV69eJYLUzJkz8cILL1R7G4iIrBXDFRHVGZ07dza57+fnB4VCUWL7nXJzc+Hs7Fzu16lfvz7q169fqTa6u7vfsz11yfTp07FlyxZ8++23mDhxosljo0aNwssvv4y8vLwyn6/VaiFJEuzsLPvf3ZQpU/DMM89g06ZNGDp0qMljOp0O3333Hdq1a4fo6OgqvY6lQ3mjRo0s+vpERJbGYYFERMX06tULLVq0wN69e9G1a1c4OzvjscceAwCsXr0aAwYMQFBQEJycnNCsWTO8+uqryMnJMTlGacO1wsPDMXToUGzevBlt27aFk5MTmjZtim+++cZkv9KGBU6ePBmurq64ePEiBg8eDFdX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1y4EBQVh165duHjxIsaMGYPWrVvjiSeeuOf7uZMsyxgxYgRcXFywZ88eFBQU4JlnnsGYMWOwe/duAMCECRPQpk0bLFmyBEqlErGxscbeyalTp0Kj0WDv3r1wcXHBmTNn4OrqWuF2VATDlQ1guCIiIiISLl68CFmW0bRp03LtP378eDz22GMm9ydPnoxnnnkGAIy9XR9++CF69+6N+Ph4BAYGol+/frC3t0doaCg6duwIQPSiuLi4YOjQoXBzc0NYWBjatGlT5ms/9thj+OCDD7B792707t0bgBgSOGrUKHh5ecHLywsvvfSScf/nnnsOmzdvxpo1a8oVrrZv346zZ8/iypUrqF+/PgDg3XffLTFP6o033jDeDg8Px4svvojVq1fjv//9L5ycnODq6go7O7u7DgP84YcfkJeXh++++84YahctWoRhw4bh/fffR0BAAADAy8sLixYtglKpRNOmTTFkyBDs2LGjUuFq+/btOHnyJOLi4hASEgIA+P777xEVFYUjR46gQ4cOiI+Px8svv2w8HyIiIozPj4+Px+jRo9GyZUsAQMOGDSvchopiuLIBrhwWSERERDXB3ln0IFnqtctBLhw+aOgJupf27dub3D979myJghDdunXDJ598AgB48MEHsXDhQjRs2BCDBg3C4MGDMWzYMNjZ2aF///4ICwszPjZo0CCMHDkSzs7O+OGHH/Cf//zHeMxNmzahe/fu6Nq1K7755hv07t0bly5dwr59+7B161YAgE6nw3vvvYfVq1cjISEBarUaarW61B650pw9exahoaHGYAUAXbp0KbHfzz//jIULF+LixYvIzs5GQUEB3N3dy/UaxV8rOjrapG3dunWDXq/H+fPnjeEqKioKSqXSuE9QUBBOnTpVodcq/pohISHGYAUAzZs3h6enJ86ePYsOHTpg+vTpePzxx/H999+jX79+ePDBB9GoUSMAwPPPP4+nn34aW7duRb9+/TB69Gi0atWqUm0pL865sgFurBZIRERENUGSxNA8S1zKGZYiIiIgSRLOnj1brv1LCyp3BjNZlo3bQkJCcP78eXz22WdwcnLCM888gx49ekCr1cLNzQ3Hjh3DypUrERQUhDfffBPR0dFIT0/H/fffj9jYWOPFEOqmTJmCtWvXIjMzE8uWLUNYWBj69u0LAPjoo4+wYMEC/Pe//8XOnTsRGxuLgQMH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hSRus2IgEREREZH1YLiyMZIkGeddZTJcERERERFZDYYrG+TmKMqxs2IgEREREZH1YLiyQYaeKw4LJCIiIiKyHgxXNsjNWDGQ5diJiIiIiKwFw5UNMlQMzGLPFRERERGR1WC4skHGYYGcc0VEREREZDUYrmyQG3uuiIiIiIisDsOVDWLPFRERERGR9WG4skGuKlGKnT1XRERERETWg+HKBhVVC2S4IiIiIiKyFgxXNshQLTA7n6XYiYiIiIisBcOVDXLjnCsiIiIiIqvDcGWDuM4VEREREZH1YbiyQYZqgQxXRERERETWg+HKBrGgBRERERGR9WG4skFujqIUe7a6ALIsW7g1REREREQEMFzZJMOwQJ1eRr5Wb+HWEBERERERwHBlk5wdlJAkcTtLzXLsRERERETWgOHKBkmSxKIWRERERERWhuHKRhnXumK4IiIiIiKyCgxXNsqVFQOJiIiIiKwKw5WNMlQM5LBAIiIiIiLrwHBlowxzrthzRURERERkHRiubJRxWGA+qwUSEREREVkDhisb5cZqgUREREREVoXhykZxWCARERERkXVhuLJRhmGBWQxXRERERERWgeHKRhmqBXKdKyIiIiIi68BwZaPcOCyQiIiIiMiqMFzZqKJqgQxXRERERETWgOHKRhkKWnDOFRERERGRdWC4slHGghZc54qIiIiIyCowXNkozrkiIiIiIrIuDFc2qni1QFmWLdwaIiIiIiJiuLJRhmGBBXoZ6gK9hVtDREREREQMVzbK2V4JSRK3s1gxkIiIiIjI4hiubJRCIcHVgfOuiIiIiIisBcOVDWPFQCIiIiIi68FwZcMMa11xIWEiIiIiIstjuLJhbo5cSJiIiIiIyFowXNkw12Ll2ImIiIiIyLIsGq727t2LYcOGITg4GJIkYf369Xfdf/fu3ZAkqcTl3Llzxn2WLl2K7t27w8vLC15eXujXrx8OHz5cze/EMriQMBERERGR9bBouMrJyUF0dDQWLVpUoeedP38eSUlJxktERITxsd27d2PcuHHYtWsXDh48iNDQUAwYMAAJCQnmbr7FuTJcERERERFZDTtLvnhMTAxiYmIq/Dx/f394enqW+tgPP/xgcn/p0qX4+eefsWPHDkycOLEyzbRahmqBmawWSERERERkcTY556pNmzYICgpC3759sWvXrrvum5ubC61WC29v7zL3UavVyMzMNLnYAlYLJCIiIiKyHjYVroKCgvDll19i7dq1WLduHSIjI9G3b1/s3bu3zOe8+uqrqFevHvr161fmPvPmzYOHh4fxEhISUh3NNztDtUAOCyQiIiIisjyLDgusqMjISERGRhrvd+nSBdeuXcOHH36IHj16lNh//vz5WLlyJXbv3g1HR8cyjztjxgxMnz7deD8zM9MmApYxXLHnioiIiIjI4myq56o0nTt3xoULF0ps//DDD/Huu+9i69ataNWq1V2PoVKp4O7ubnKxBa4qUYqd61wREREREVmeTfVcleb48eMICgoy2fbBBx9g7ty52LJlC9q3b2+hllU/V/ZcERERERFZDYuGq+zsbFy8eNF4Py4uDrGxsfD29kZoaChmzJiBhIQEfPfddwCAhQsXIjw8HFFRUdBoNFixYgXWrl2LtWvXGo8xf/58zJw5Ez/++CPCw8ORnJwMAHB1dYWrq2vNvsFqZihokaVmtUAiIiIiIkuzaLg6evQoevfubbxvmPc0adIkLF++HElJSYiPjzc+rtFo8NJLLyEhIQFOTk6IiorChg0bMHjwYOM+ixcvhkajwQMPPGDyWrNmzcLs2bOr9w3VMM65IiIiIiKyHpIsy7KlG2FtMjMz4eHhgYyMDKuef5WUkYcu83bCXinh37kxkCTJ0k0iIiIiIqpVKpINbL6gRV1mGBao1clQF+gt3BoiIiIiorqN4cqGuTgUjerkWldERERERJbFcGXDFArJ2HvFeVdERERERJbFcGXjjBUDGa6IiIiIiCyK4crGGda6Yjl2IiIiIiLLYriycSzHTkRERERkHRiubJxxzhULWhARERERWRTDlY0z9lwxXBERERERWRTDlY1jQQsiIiIiIuvAcGXjXFX2ABiuiIiIiIgsjeHKxrkahwWyWiARERERkSUxXNk4Ny4iTERERERkFRiubBwLWhARERERWQeGKxtnXESYPVdERERERBbFcGXjuM4VEREREZF1YLiycW7suSIiIiIisgoMVzbOUIqdPVdERERERJbFcGXjjKXY2XNFRERERGRRDFc2zjAsUKPTQ12gs3BriIiIiIjqLoYrG+fiYGe8zd4rIiIiIiLLYbiycUqFBBcHJQDOuyIiIiIisiSGq1qAa10REREREVkew1UtYFjriuGKiIiIiMhyGK5qAVdHlmMnIiIiIrI0hqta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u3aws7ODnZ0d9uzZg08//RR2dnbGc4TnD5WHi4sLWrZsiQsXLtjsvz0MV9XMwcEB7dq1w7Zt20y2b9u2DV27drVQq8gWNWjQAIGBgSbnkkajwZ49e3guEWRZxrPPPot169Zh586daNCggcnjPH+oomRZhlqt5rlDd9W3b1+cOnUKsbGxxkv79u0xYcIExMbGomHDhjx/qNzUajXOnj2LoKAgm/23h8MCa8D06dPxyCOPoH379ujSpQu+/PJLxMfH46mnnrJ008jKZGdn4+LFi8b7cXFxiI2Nhbe3N0JDQzFt2jS8++67iIiIQEREBN599104Oztj/PjxFmw1WYOpU6fixx9/xK+//go3NzfjX/o8PDzg5ORkXHeG5w+V5rXXXkNMTAxCQkKQlZWFVatWYffu3di8eTPPHborNzc349xOAxcXF/j4+Bi38/yhsrz00ksYNmwYQkNDkZKSgrlz5yIzMxOTJk2y3X97LFansI757LPP5LCwMNnBwUFu27atsTwyUXG7du2SAZS4TJo0SZZlUZZ01qxZcmBgoKxSqeQePXrIp06dsmyjySqUdt4AkJctW2bch+cPleWxxx4z/h/l5+cn9+3bV966davxcZ47VBHFS7HLMs8fKtuYMWPkoKAg2d7eXg4ODpZHjRolnz592vi4LZ47kizLsoVyHRERERERUa3BOVdERERERERmwHBFRERERERkBgxXREREREREZsBwRUREREREZAYMV0RERERERGbAcEVERERERGQGDFdERERERERmwHBFRERERERkBgxXREREZiZJEtavX2/pZhARUQ1juCIiolpl8uTJkCSpxGXQoEGWbhoREdVydpZuABERkbkNGjQIy5YtM9mmUqks1BoiIqor2HNFRES1jkqlQmBgoMnFy8sLgBiyt2TJEsTExMDJyQkNGjTAmjVrTJ5/6tQp9OnTB05OTvDx8cGTTz6J7Oxsk32++eYbREVFQaVSISgoCM8++6zJ4zdv3sTIkSPh7OyMiIgI/Pbbb9X7pomIyOIYroiIqM6ZOXMmRo8ejRMnTuDhhx/GuHHjcPbsWQBAbm4uBg0aBC8vLxw5cgRr1qzB9u3bTcLTkiVLMHXqVDz55JM4deoUfvvtNzRu3NjkNd566y089NBDOHnyJAYPHowJEybg1q1bNfo+iYioZkmyLMuWbgQREZG5TJ48GStWrICjo6PJ9ldeeQUzZ86EJEl46qmnsGTJEuNjnTt3Rtu2bbF48WIsXboUr7zyCq5duwYXFxcAwMaNGzFs2DAkJiYiICAA9erVw6OPPoq5c+eW2gZJkvDGG29gzpw5AICcnBy4ublh48aNnPtFRFSLcc4VERHVOr179zYJTwDg7e1tvN2lSxeTx7p06YLY2FgAwNmzZxEdHW0MVgDQrVs36PV6nD9/HpIkITExEX379r1rG1q1amW87eLiAjc3N6SkpFT2LRERkQ1guCIiolrHxcWlxDC9e5EkCQAgy7Lxdmn7ODk5let49vb2JZ6r1+sr1CYiIrItnHNFRER1zqFDh0rcb9q0KQCgefPmiI2NRU5OjvHx/fv3Q6FQoEmTJnBzc0N4eDh27NhRo20mIiLrx54rIiKqddRqNZKTk0222dnZwdfXFwCwZs0atG/fHvfddx9++OEHHD58GF9//TUAYMKECZg1axYmTZqE2bNnIzU1Fc899xweeeQRBAQEAABmz56Np556Cv7+/oiJiUFWVhb279+P5557rmbfKBERWRWGKyIiqnU2b96MoKAgk22RkZE4d+4cAFHJb9WqVXjmmWcQGBiIH374Ac2bNwcAODs7Y8uWLXjhhRfQoUMHODs7Y/To0fj444+Nx5o0aRLy8/OxYMECvPTSS/D19cUDDzxQc2+QiIisEqsFEhFRnSJJEn755ReMGDHC0k0hIqJahnOuiIiIiIiIzIDhioiIiIiIyAw454qIiOoUjoYnIqLqwp4rIiIiIiIiM2C4IiIiIiIiMgOGKyIiIiIiIjNguCIiIiIiIjIDhisiIiIiIiIzYLgiIiIiIiIyA4YrIiIiIiIiM2C4IiIiIiIiMoP/B7QQ7Z1EzRe3AAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 1000x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Calculate and print accuracies for training and cross-validation sets\n",
    "model.eval()\n",
    "with torch.no_grad():\n",
    "    # Training set accuracy\n",
    "    tr_correct = 0\n",
    "    tr_total = 0\n",
    "    for images, labels in trLoader:\n",
    "        outputs = model(images)\n",
    "        _, predicted = torch.max(outputs, 1)\n",
    "        _, true_labels = torch.max(labels, 1)\n",
    "        tr_total += labels.size(0)\n",
    "        tr_correct += (predicted == true_labels).sum().item()\n",
    "    \n",
    "    tr_accuracy = 100 * tr_correct / tr_total\n",
    "    \n",
    "    # Test set accuracy\n",
    "    cv_correct = 0\n",
    "    cv_total = 0\n",
    "    for images, labels in cvLoader:\n",
    "        outputs = model(images)\n",
    "        _, predicted = torch.max(outputs, 1)\n",
    "        _, true_labels = torch.max(labels, 1)\n",
    "        cv_total += labels.size(0)\n",
    "        cv_correct += (predicted == true_labels).sum().item()\n",
    "    \n",
    "    cv_accuracy = 100 * cv_correct / cv_total\n",
    "\n",
    "print(f'Accuracy on training set: {tr_accuracy:.2f}%')\n",
    "print(f'Accuracy on cross-validation set: {cv_accuracy:.2f}%')\n",
    "\n",
    "# Plot training and cross-validation losses\n",
    "plt.figure(figsize=(10, 5))\n",
    "plt.plot(range(1, num_epochs+1), train_losses, label='Training Loss')\n",
    "plt.plot(range(1, num_epochs+1), cv_losses, label='Cross-Validation Loss')\n",
    "plt.xlabel('Epoch')\n",
    "plt.ylabel('Loss')\n",
    "plt.title('Training and Cross-Validation Loss')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.14"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
